<template>
	<el-dialog fullscreen title="代码预览" v-model="visible" width="90%" top="3vh" append-to-body :close-on-click-modal="false">
		<splitpanes>
			<pane size="25">
				<el-scrollbar height="calc(100vh - 100px)" class="mt20">
					<el-tree
						ref="treeRef"
						node-key="id"
						:data="preview.fileTree"
						:expand-on-click-node="false"
						highlight-current
						@node-click="handleNodeClick"
					/>
				</el-scrollbar>
			</pane>
			<pane>
				<el-tabs v-model="preview.activeName" @tab-click="handleTabClick">
					<el-tab-pane
						v-for="item in previewCodegen"
						:label="item.codePath.substring(item.codePath.lastIndexOf('/') + 1)"
						:name="item.codePath"
						:key="item.codePath"
					>
						<SvgIcon name="ele-CopyDocument" :size="25" class="copy_btn" @click="copyText(item.code)" />
					</el-tab-pane>
					<code-editor ref="codeEditorRef" theme="darcula" v-model="previewCodeStr" mode="go" readOnly height="calc(100vh - 100px)"></code-editor>
				</el-tabs>
			</pane>
		</splitpanes>
	</el-dialog>
</template>
<script setup lang="ts" name="preview">
import { useGeneratorPreviewApi } from '/@/api/gen/table'
import { handleTree } from '/@/utils/other'
import commonFunction from '/@/utils/commonFunction'
const CodeEditor = defineAsyncComponent(() => import('/@/components/CodeEditor/index.vue'))

const { copyText } = commonFunction()

const visible = ref(false)
// ======== 显示页面 ========
const preview = reactive({
	open: false,
	titel: '代码预览',
	fileTree: [],
	activeName: '',
})

interface ICodegen {
	codePath: string
	code: string
	[key: string]: any
}
const previewCodegen = ref<ICodegen[]>([])
const previewCodeStr = ref('')
const fileTreeOriginal = ref([] as any[])

const openDialog = async (id: string) => {
	await getGenCodeFile(id)
	visible.value = true
}

const loading = ref(false)
const codeEditorRef = ref()

/**
 * 获取特定资源的代码生成文件，显示在页面上。
 * @param id 需要渲染的资源 ID。
 */
const getGenCodeFile = (id: string) => {
	loading.value = true
	fileTreeOriginal.value = []
	useGeneratorPreviewApi(id)
		.then((res: any) => {
			previewCodegen.value = res
			for (let index in res) {
				fileTreeOriginal.value.push(res[index].codePath)
			}
			// 默认选中第一个 选项卡
			previewCodeStr.value = res[0].code
			preview.activeName = res[0].codePath
			const files = handleFiles(fileTreeOriginal)
			preview.fileTree = handleTree(files, 'id', 'parentId', 'children', '/')
		})
		.finally(() => {
			loading.value = false
		})
}

const handleNodeClick = async (data: any, node: any) => {
	if (node && !node.isLeaf) {
		return false
	}

	preview.activeName = data.id

	const filteredCode = previewCodegen.value.filter((code: any) => code.codePath === data.id)
	if (filteredCode.length > 0) {
		previewCodeStr.value = filteredCode[0].code
	}
}

const handleTabClick = (item: any) => {
	const filteredCode = previewCodegen.value.filter((code: any) => code.codePath === item.paneName)
	if (filteredCode.length > 0) {
		previewCodeStr.value = filteredCode[0].code
	}
}

/**
 * 生成 files 目录
 * @param fileTreeOriginal
 * @returns {*[]}
 */
const handleFiles = (fileTreeOriginal: any) => {
	const exists = {}
	const files = [] as any[]

	// 遍历每个元素
	for (const data of fileTreeOriginal.value) {
		let paths = []
		if (data.includes('\\')) {
			paths = data.split('\\')
		} else {
			paths = data.split('/')
		}
		let fullPath = '' // 从头开始的路径，用于生成 id
		// 遍历每个 path， 拼接成树
		for (let i = 0; i < paths.length; i++) {
			// 已经添加到 files 中，则跳过
			const oldFullPath = fullPath
			// 下面的 replaceAll 的原因，是因为上面包处理了，导致和 tabs 不匹配，所以 replaceAll 下
			fullPath = fullPath.length === 0 ? paths[i] : fullPath.replaceAll('.', '/') + '/' + paths[i]
			if (exists[fullPath]) {
				continue
			}
			// 添加到 files 中
			exists[fullPath] = true
			files.push({
				id: fullPath,
				label: paths[i],
				parentId: oldFullPath || '/',
				templateName: data.k,
			})
		}
	}
	return files
}

defineExpose({
	openDialog,
})
</script>

<style scoped lang="scss">
.copy_btn {
	position: absolute;
	top: 10px;
	right: 20px;
	z-index: 9;
	color: white;
}
</style>
